package com.azier.compare;

import com.azier.annotation.CompareField;
import com.azier.util.ClassUtil;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 1 * @Author: luoj
 * 2 * @Date: 2019/8/20 14:26
 * 3 比较方法的并发实现
 * 除非比较发生比较频繁，否则不建议使用
 */
public class CompareCurrent {
    //缓存用过的Class结构
    /**
     * 缓存用过的Class结构
     */
    private static final ConcurrentMap<String, LinkedList<Field>> CLASS_FIELD_CACHE = new ConcurrentHashMap<>();

    public static <T> Map<Field, Map<String, Object>> compare(T o1, T o2, Class<T> t, boolean equals) throws IllegalAccessException {
        cacheMeasurementClass(t);
        List<Field> fieldList = CLASS_FIELD_CACHE.get(t.getName());
        return Compare.compareBase(o1, o2, equals, fieldList);
    }

    static void cacheMeasurementClass(final Class clazz) {
        if (CLASS_FIELD_CACHE.containsKey(clazz.getName())) {
            return;
        }
        LinkedList<Field> initialLinkedList = new LinkedList<>();
        LinkedList<Field> linkedListFieldList = CLASS_FIELD_CACHE.putIfAbsent(clazz.getName(), initialLinkedList);
        if (linkedListFieldList == null) {
            linkedListFieldList = initialLinkedList;
        }

        linkedListFieldList.addAll(ClassUtil.getFieldLinkList(clazz));
    }

    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回相同字段
     * @param o1
     * @param o2
     * @param <T>
     * @return Map<字段,Map<o，value>>
     */
    public static <T> Map<Field, Map<String, Object>> compareEquals(T o1, T o2,Class<T> t) throws IllegalAccessException {
        return compare(o1,o2,t,true);
    }
    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回不同字段
     * @param o1
     * @param o2
     * @param <T>
     * @return Map<字段,Map<o1 o2，value>>
     */
    public static <T> Map<Field, Map<String, Object>> compareNotEquals(T o1, T o2,Class<T> t) throws IllegalAccessException {
        return compare(o1,o2,t,false);
    }

    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回相同字段
     * @param o1
     * @param o2
     * @param <T>
     * @return Map<字段,Map<o，value>>
     */
    public static <T> Map<String, Map<String, Object>> compareEqualsStringField(T o1, T o2,Class<T> t) throws IllegalAccessException {
        Map<Field, Map<String, Object>> result = compare(o1,o2,t,true);
        return getField2StringMap(result);
    }
    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回不同字段
     * @param o1
     * @param o2
     * @param <T>
     * @return Map<字段,Map<o1 o2，value>>
     */
    public static <T> Map<String, Map<String, Object>> compareNotEqualsStringField(T o1, T o2,Class<T> t) throws IllegalAccessException {
        Map<Field, Map<String, Object>> result = compare(o1,o2,t,false);;
        return getField2StringMap(result);
    }
    private static Map<String, Map<String, Object>> getField2StringMap(Map<Field, Map<String, Object>> result) {
        Map<String, Map<String, Object>> stringField = new HashMap<>();
        if (result != null && !result.isEmpty()) {
            for (Map.Entry<Field, Map<String, Object>> entry : result.entrySet()) {
                CompareField compareField = entry.getKey().getAnnotation(CompareField.class);
                if (compareField != null) {
                    stringField.put(compareField.name(), entry.getValue());
                } else {
                    stringField.put(entry.getKey().getName(), entry.getValue());
                }
            }
        }
        return stringField;
    }
}

